Skip to content

feat: KYC controller#9615

Open
Akaryatrh wants to merge 19 commits into
mainfrom
feat/kyc-controller
Open

feat: KYC controller#9615
Akaryatrh wants to merge 19 commits into
mainfrom
feat/kyc-controller

Conversation

@Akaryatrh

@Akaryatrh Akaryatrh commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@metamask/kyc-controller

Overview

@metamask/kyc-controller is a shared, platform-agnostic KYC / identity-verification package for MetaMask clients (mobile, extension, web). It centralizes all KYC orchestration logic in the core monorepo so every client consumes one implementation instead of maintaining its own.

What's included

Core modules

  • KycController (src/KycController.ts) — A BaseController that owns the entire identity flow:

    • The flow state machine: idle → terms → session → check → auth → form → submit → done / error.
    • The Check/Auth frame message protocol for communicating with MoonPay's hosted frames (blocks.moonpay.com) over dedicated channels (ch_1, ch_2, ch_reset).
    • X25519 credential decryption and key-pair generation.
    • SumSub orchestration through an injected KycSumSubLauncher adapter, keeping the controller SDK-free while each client injects its own launcher.
    • Product-scoped auto-continuation: an optional product (ramps | card) passed to initialize / acceptTermsAndStartSession is stored as activeProduct. Once authentication reaches the form phase, the controller automatically runs the KYC-required check and, when KYC is required, chains into the SumSub sub-flow — with no extra consumer calls. Without a product, the flow stops at form for manual control (checkKycRequired / startSumSub).
    • A per-product "is KYC required" cache and security-aware state metadata (session/access tokens are marked non-persisted and non-logged).
  • KycService (src/KycService.ts) — A data service that performs the Universal KYC (UKYC) HTTP calls via an injected fetch. It wraps requests with createServicePolicy for resilience, validates responses with superstruct, and sources the auth bearer token (from profile-sync-controller) and geolocation (from geolocation-controller) through the messenger. It also accepts an optional baseUrl to override the env-derived URL for local/staging APIs.

Supporting modules

  • crypto.ts — X25519 key-pair generation and encrypted-credential decryption.
  • countryCodes.ts — ISO 3166-1 alpha-2 → alpha-3 country-code mapping.
  • selectors.ts — Memoized state selectors (selectKycPhase, selectKycSumSub, selectIsKycRequiredForProduct).
  • types.ts — Shared vendor-neutral types (KycPhase, KycProduct, KycVendor, KycSumSubLauncher, KycDisclaimer, etc.).
  • KycController-method-action-types.ts / KycService-method-action-types.ts — Messenger action type definitions for the controller and service.
  • index.ts — Explicit (non-barrel) exports defining the package's public API.

Tests

Comprehensive Jest test suites covering the controller, service, crypto, country codes, selectors, and the index/public API (KycController.ts at 100% coverage, including the new auto-continuation paths).

Package scaffolding & monorepo wiring

  • Standard package files: package.json, tsconfig.json, tsconfig.build.json, jest.config.js, typedoc.json, CHANGELOG.md, README.md, and the LICENSE, LICENSE.APACHE2, and LICENSE.MIT files.
  • Registered in the root tsconfig.json / tsconfig.build.json project references, added to the root README.md package list, and reflected in yarn.lock.

Public API

The package explicitly exports:

  • Controller: KycController, getDefaultKycControllerState, controllerName, plus its messenger, options, state, action, and event types. initialize / acceptTermsAndStartSession accept an optional product to enable the automatic post-authentication continuation.
  • Service: KycService, serviceName, plus its messenger, options, params, response, action, and event types.
  • Selectors: selectIsKycRequiredForProduct, selectKycPhase, selectKycSumSub.
  • Utilities: alpha2ToAlpha3, ALPHA2_TO_ALPHA3, decryptCredentials, generateKeyPair, and related crypto/domain types.

Note

The SumSub sub-flow currently uses placeholders (MOCK_JWT_TOKEN and a hardcoded vendorUserId), which must be replaced with real UKYC-issued credentials before production use.

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
New identity/KYC path handles bearer tokens, decrypted frame credentials, and persisted terms/cache; production readiness depends on replacing mock UKYC JWT/vendor IDs and correct client frame-origin handling.

Overview
Introduces @metamask/kyc-controller, a new monorepo package that centralizes KYC / identity verification for MetaMask clients behind a vendor-neutral ramps / card product surface.

KycController orchestrates the full flow (terms → MoonPay session → Check/Auth frames → optional KYC check → SumSub document verification), including frame postMessage handling, X25519 + AES-GCM credential decryption, generation guards so reset() does not apply stale async results, and optional product on initialize / acceptTermsAndStartSession so post-auth KYC check and SumSub can run automatically. KycService is a stateless UKYC HTTP client (bearer token + geolocation via messenger, superstruct validation, optional baseUrl override). SumSub UI is injected through KycSumSubLauncher.

Also adds package scaffolding (tests at 100% coverage threshold, README, licenses), root README / dependency graph entries, and CODEOWNERS / codeowners.ts for @MetaMask/universal-kyc. Note: SumSub UKYC session creation still uses placeholders (MOCK_JWT_TOKEN, hardcoded vendorUserId) until real credentials are wired.

Reviewed by Cursor Bugbot for commit 2c4805d. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread packages/kyc-controller/src/KycService.ts
Comment thread packages/kyc-controller/src/KycController.ts
Comment thread packages/kyc-controller/src/KycController.ts
@Akaryatrh Akaryatrh changed the title feat: init KYC controller and add logic from mobile repo feat: KYC controller Jul 23, 2026
Comment thread packages/kyc-controller/src/KycController.ts Outdated
@Akaryatrh
Akaryatrh force-pushed the feat/kyc-controller branch from ac34b99 to a61e704 Compare July 23, 2026 15:11
Comment thread packages/kyc-controller/src/KycController.ts
@socket-security

socket-security Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedjest@​29.7.01001006889100
Added@​types/​jest@​29.5.141001007780100
Addedchokidar-cli@​3.0.09910010083100
Addedyargs@​17.7.38610010089100

View full report

@socket-security

socket-security Bot commented Jul 23, 2026

Copy link
Copy Markdown

Warning

MetaMask internal reviewing guidelines:

  • Do not ignore-all
  • Each alert has instructions on how to review if you don't know what it means. If lost, ask your Security Liaison or the supply-chain group
  • Copy-paste ignore lines for specific packages or a group of one kind with a note on what research you did to deem it safe.
    @SocketSecurity ignore npm/PACKAGE@VERSION
Action Severity Alert  (click "▶" to expand/collapse)
Warn Low
Potential code anomaly (AI signal): npm y18n is 68.0% likely to have a medium risk anomaly

Notes: The code is a standard local i18n helper that caches locale strings and writes updates to disk. It does not contain obvious malware or backdoors. However, there are security concerns related to unvalidated locale inputs, potential path traversal when locale is attacker-controlled, and race conditions in multi-process environments. If used in attack-prone contexts, these issues should be mitigated by validating locale values, constraining file paths within the intended directory, and optionally disabling auto-write-back (updateFiles=false) in high-risk deployments.

Confidence: 0.68

Severity: 0.58

From: ?npm/chokidar-cli@3.0.0npm/y18n@4.0.3

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/y18n@4.0.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm yargs is 61.0% likely to have a medium risk anomaly

Notes: The module implements a standard extends resolution with circular-extends protection and recursive merging. Primary security concerns are the potential execution of arbitrary code when extends points to a JS module and possible disclosure of local files via path-based extends. Treat untrusted inputs as a high-risk factor; consider enforcing whitelisting of allowed extends or sandboxing JS module extends. Overall risk is moderate due to code execution potential from untrusted configuration sources.

Confidence: 0.61

Severity: 0.58

From: ?npm/chokidar-cli@3.0.0npm/yargs@13.3.2

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/yargs@13.3.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm yargs is 68.0% likely to have a medium risk anomaly

Notes: The provided code consists of harmless-looking shell completion templates used to generate Bash/Zsh completions by querying the application for possible commands via --get-yargs-completions. There is no malicious behavior evident in the template code itself. The main risk is dependency on the integrity of the app_path binary that provides completions; if that binary is compromised, it could influence completions or run unintended commands. Overall, low likelihood of malware in these templates themselves.

Confidence: 0.68

Severity: 0.60

From: ?npm/chokidar-cli@3.0.0npm/yargs@13.3.2

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/yargs@13.3.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Ignoring alerts on:

  • chokidar-cli@3.0.0
  • create-jest@29.7.0
  • yargs@17.7.3
  • istanbul-lib-source-maps@4.0.1
  • babel-plugin-istanbul@6.1.1

View full report

Comment thread packages/kyc-controller/src/KycController.ts
Comment thread packages/kyc-controller/src/KycController.ts
* (disclaimers, kyc-required) expect alpha-3 codes (e.g. "USA"). This map
* bridges the two.
*/
export const ALPHA2_TO_ALPHA3: Record<string, string> = {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thoughts on this living in a different package or in the client for now?

I think the KYC Controller interface should expect the country code to be in 3 character format

@Akaryatrh

Copy link
Copy Markdown
Contributor Author

@SocketSecurity ignore npm/yargs@17.7.3
@SocketSecurity ignore npm/chokidar-cli@3.0.0
@SocketSecurity ignore npm/babel-plugin-istanbul@6.1.1
@SocketSecurity ignore npm/create-jest@29.7.0
@SocketSecurity ignore npm/istanbul-lib-source-maps@4.0.1

Comment thread packages/kyc-controller/src/KycController.ts
Comment thread packages/kyc-controller/src/KycController.ts
Comment thread packages/kyc-controller/src/KycController.ts
Comment thread packages/kyc-controller/src/KycService.ts Outdated
@Akaryatrh

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

Comment thread packages/kyc-controller/src/KycController.ts
Akaryatrh added 15 commits July 24, 2026 12:26
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
…b flow opening

Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
… been reset

Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
@Akaryatrh
Akaryatrh force-pushed the feat/kyc-controller branch from 11d7853 to 194d216 Compare July 24, 2026 10:29

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 194d216. Configure here.

Comment thread packages/kyc-controller/src/KycController.ts
Comment thread packages/kyc-controller/src/KycController.ts
@github-actions

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.5-preview-11d78534e
@metamask-previews/accounts-controller@39.0.5-preview-11d78534e
@metamask-previews/address-book-controller@7.1.2-preview-11d78534e
@metamask-previews/ai-controllers@0.8.0-preview-11d78534e
@metamask-previews/analytics-controller@1.2.1-preview-11d78534e
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-11d78534e
@metamask-previews/announcement-controller@8.1.0-preview-11d78534e
@metamask-previews/app-metadata-controller@2.0.1-preview-11d78534e
@metamask-previews/approval-controller@9.0.2-preview-11d78534e
@metamask-previews/assets-controller@11.2.0-preview-11d78534e
@metamask-previews/assets-controllers@110.0.0-preview-11d78534e
@metamask-previews/authenticated-user-storage@3.0.1-preview-11d78534e
@metamask-previews/base-controller@9.1.0-preview-11d78534e
@metamask-previews/base-data-service@0.1.3-preview-11d78534e
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-11d78534e
@metamask-previews/bridge-controller@78.0.0-preview-11d78534e
@metamask-previews/bridge-status-controller@74.5.0-preview-11d78534e
@metamask-previews/build-utils@3.0.4-preview-11d78534e
@metamask-previews/chain-agnostic-permission@1.7.0-preview-11d78534e
@metamask-previews/chomp-api-service@4.0.0-preview-11d78534e
@metamask-previews/claims-controller@0.5.3-preview-11d78534e
@metamask-previews/client-controller@1.0.1-preview-11d78534e
@metamask-previews/client-utils@1.2.1-preview-11d78534e
@metamask-previews/compliance-controller@2.1.0-preview-11d78534e
@metamask-previews/composable-controller@12.0.1-preview-11d78534e
@metamask-previews/config-registry-controller@0.4.1-preview-11d78534e
@metamask-previews/connectivity-controller@0.3.0-preview-11d78534e
@metamask-previews/controller-utils@12.3.0-preview-11d78534e
@metamask-previews/core-backend@7.0.0-preview-11d78534e
@metamask-previews/delegation-controller@3.0.2-preview-11d78534e
@metamask-previews/earn-controller@12.2.2-preview-11d78534e
@metamask-previews/eip-5792-middleware@3.0.5-preview-11d78534e
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-11d78534e
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-11d78534e
@metamask-previews/ens-controller@19.1.5-preview-11d78534e
@metamask-previews/eth-block-tracker@15.0.1-preview-11d78534e
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-11d78534e
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-11d78534e
@metamask-previews/foundryup@1.0.1-preview-11d78534e
@metamask-previews/gas-fee-controller@26.3.0-preview-11d78534e
@metamask-previews/gator-permissions-controller@4.2.3-preview-11d78534e
@metamask-previews/geolocation-controller@0.1.3-preview-11d78534e
@metamask-previews/java-tron-up@1.0.0-preview-11d78534e
@metamask-previews/json-rpc-engine@10.5.0-preview-11d78534e
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-11d78534e
@metamask-previews/keyring-controller@27.1.0-preview-11d78534e
@metamask-previews/kyc-controller@0.0.0-preview-11d78534e
@metamask-previews/local-node-utils@1.0.0-preview-11d78534e
@metamask-previews/logging-controller@8.0.2-preview-11d78534e
@metamask-previews/message-manager@14.1.2-preview-11d78534e
@metamask-previews/messenger@2.0.0-preview-11d78534e
@metamask-previews/messenger-cli@0.2.0-preview-11d78534e
@metamask-previews/money-account-api-data-service@0.3.0-preview-11d78534e
@metamask-previews/money-account-balance-service@2.3.0-preview-11d78534e
@metamask-previews/money-account-controller@0.3.3-preview-11d78534e
@metamask-previews/money-account-upgrade-controller@3.0.0-preview-11d78534e
@metamask-previews/multichain-account-service@13.0.0-preview-11d78534e
@metamask-previews/multichain-api-middleware@4.0.1-preview-11d78534e
@metamask-previews/multichain-network-controller@3.2.1-preview-11d78534e
@metamask-previews/multichain-transactions-controller@7.1.1-preview-11d78534e
@metamask-previews/name-controller@9.1.2-preview-11d78534e
@metamask-previews/network-connection-banner-controller@0.1.0-preview-11d78534e
@metamask-previews/network-controller@34.0.0-preview-11d78534e
@metamask-previews/network-enablement-controller@5.6.0-preview-11d78534e
@metamask-previews/notification-services-controller@26.0.0-preview-11d78534e
@metamask-previews/passkey-controller@3.0.0-preview-11d78534e
@metamask-previews/permission-controller@13.1.1-preview-11d78534e
@metamask-previews/permission-log-controller@5.1.0-preview-11d78534e
@metamask-previews/perps-controller@10.0.0-preview-11d78534e
@metamask-previews/phishing-controller@17.3.0-preview-11d78534e
@metamask-previews/platform-api-docs@0.0.0-preview-11d78534e
@metamask-previews/polling-controller@16.0.8-preview-11d78534e
@metamask-previews/preferences-controller@23.1.0-preview-11d78534e
@metamask-previews/profile-metrics-controller@4.0.2-preview-11d78534e
@metamask-previews/profile-sync-controller@28.3.0-preview-11d78534e
@metamask-previews/ramps-controller@17.1.0-preview-11d78534e
@metamask-previews/rate-limit-controller@7.0.1-preview-11d78534e
@metamask-previews/react-data-query@0.2.2-preview-11d78534e
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-11d78534e
@metamask-previews/sample-controllers@5.0.3-preview-11d78534e
@metamask-previews/seedless-onboarding-controller@10.1.0-preview-11d78534e
@metamask-previews/selected-network-controller@26.1.5-preview-11d78534e
@metamask-previews/sentinel-api-service@1.0.0-preview-11d78534e
@metamask-previews/shield-controller@5.1.3-preview-11d78534e
@metamask-previews/signature-controller@39.2.7-preview-11d78534e
@metamask-previews/smart-transactions-controller@25.0.1-preview-11d78534e
@metamask-previews/snap-account-service@2.0.0-preview-11d78534e
@metamask-previews/social-controllers@2.6.0-preview-11d78534e
@metamask-previews/solana-test-validator-up@1.0.0-preview-11d78534e
@metamask-previews/stellar-quickstart-up@0.0.0-preview-11d78534e
@metamask-previews/storage-service@1.0.2-preview-11d78534e
@metamask-previews/subscription-controller@6.2.1-preview-11d78534e
@metamask-previews/transaction-controller@69.2.1-preview-11d78534e
@metamask-previews/transaction-pay-controller@26.0.0-preview-11d78534e
@metamask-previews/user-operation-controller@41.2.7-preview-11d78534e
@metamask-previews/wallet@8.1.0-preview-11d78534e
@metamask-previews/wallet-cli@0.0.0-preview-11d78534e

Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
@Akaryatrh
Akaryatrh requested a review from a team as a code owner July 24, 2026 15:37
Signed-off-by: Sébastien Van Eyck <sebastien.vaneyck@consensys.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants